package org.siteanalyser.service.impl;

import java.io.IOException;

import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.siteanalyser.domain.Message;
import org.siteanalyser.service.Service;
import org.siteanalyser.service.SystemException;
import org.siteanalyser.util.HtmlParseUtil;

public class CrawlerServiceImpl implements Service {

    public void process(final Message message) throws SystemException {
        makeRequest(message);
    }

    private void makeRequest(final Message message) {
        final String url = message.getRequest().getUrl();
        Document doc = null;
        try {
            doc = Jsoup.connect(url).get();
        } catch (final IOException e) {
            throw new SystemException(e.getMessage());
        }
        if (doc == null) {
            throw new SystemException(String.format("Unable to parse URL: %s", url));
        }
        addStatistics(message, doc);
    }

    private void addStatistics(final Message message, final Document doc) {
        getLinksWithoutAlt(doc, message);
        getHeadingsCount(doc, message);
        getMetadata(doc, message);
        getPageTitles(doc, message);
        getUrlStructure(doc, message);
        getTextRatio(doc, message);
        getGoogleAnalytics(doc, message);
    }

    private void getGoogleAnalytics(final Document doc, final Message message) {
        final boolean isAnalyticsPresent = HtmlParseUtil.getGoogleAnalytics(doc);
        message.getReport().addReportItem("googleanalytics", isAnalyticsPresent);
    }

    private void getTextRatio(final Document doc, final Message message) {
        final long percentage = Math.round(HtmlParseUtil.getTextPercentage(doc));
        message.getReport().addReportItem("texthtmlratio", percentage);
    }

    private void getUrlStructure(final Document doc, final Message message) {
        final Elements links = doc.select("a");
        int badUrlCount = 0;
        for (final Element link : links) {
            final String href = link.attr("href");
            if (href.contains("?")) {
                badUrlCount++;
            }
        }
        message.getReport().addReportItem("urlstructure", badUrlCount);
    }

    private void getPageTitles(final Document doc, final Message message) {
        final Elements titles = doc.select("title");
        message.getReport().addReportItem("pagetitles", "" + titles.size());
    }

    private void getMetadata(final Document doc, final Message message) {
        final Elements meta = doc.select("meta");
        int descriptionCount = 0;
        int keywordsCount = 0;
        for (final Element element : meta) {
            final String description = element.attr("name");
            if (StringUtils.equalsIgnoreCase(description, "description")) {
                descriptionCount++;
            } else if (StringUtils.equalsIgnoreCase(description, "keywords")) {
                keywordsCount++;
            }
        }
        message.getReport().addReportItem("metadescription", descriptionCount);
        message.getReport().addReportItem("metakeywords", keywordsCount);
    }

    private void getHeadingsCount(final Document doc, final Message message) {
        final Elements headings = doc.select("h1");
        message.getReport().addReportItem("headings", headings.size());
    }

    private void getLinksWithoutAlt(final Document doc, final Message message) {
        final Elements images = doc.select("img");
        int missingCount = 0;
        for (final Element element : images) {
            final String alt = element.attr("alt");
            if (StringUtils.isEmpty(alt)) {
                missingCount++;
            }
        }
        message.getReport().addReportItem("imagealtattributes", missingCount);
    }

}
